﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeArt.SharePoint.CamlQuery
{
    public interface IWhereable
    {
    }
    /// <summary>
    /// 直接关联
    /// </summary>
    public interface IDirectJoinable
    {
    }
    /// <summary>
    /// 间接关联
    /// </summary>
    public interface IRelatedJoinable
    {
    }

    /// <summary>
    /// 扩展方式
    /// </summary>
    public static class CamlExtension
    {
        /// <summary>
        /// combine two Caml expression
        /// </summary>
        /// <param name="expr1"></param>
        /// <param name="expr2"></param>
        /// <returns></returns>
        public static CamlExpression Combine(this CamlExpression expr1, CamlExpression expr2)
        {
            if (expr1 == null)
                return expr2;
            else if (expr2 == null)
                return expr1;
            else
                return expr1 && expr2;
        }
        /// <summary>
        /// filter
        /// </summary>
        /// <param name="whereable">the query sentense</param>
        /// <param name="expr">expression</param>
        /// <returns></returns>
        public static Where Where(this IWhereable whereable, ICamlExpression expr)
        {
            var sentense = (QuerySentence)whereable;
            return new Where(sentense.Context,expr);
        }
        /// <summary>
        /// order by
        /// </summary>
        /// <param name="whereable">the query sentense</param>
        /// <param name="field">the fidle to order</param>
        /// <returns></returns>
        public static Order OrderBy(this IWhereable whereable,IQueryField field)
        {
            var sentense = (QuerySentence)whereable;
            return new Order(sentense.Context, field, true);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="whereable">the query sentense</param>
        /// <param name="field">the field to order</param>
        /// <param name="desc">desc or Esc</param>
        /// <returns></returns>
        public static Order OrderBy(this IWhereable whereable,IQueryField field, bool desc)
        {
            var sentense = (QuerySentence)whereable;
            return new Order(sentense.Context, field, desc);
        }

        #region join able
        /// <summary>
        /// join query
        /// </summary>
        /// <param name="joinable">the query sentense</param>
        /// <param name="joinType">join type</param>
        /// <param name="field">the lookup field to join</param>
        /// <returns></returns>
        public static Join Join(this IDirectJoinable joinable, JoinType joinType, string field)
        {
            var sentense = (QuerySentence)joinable;
            return new Join(sentense.Context, joinType, field);
        }
        /// <summary>
        /// join query
        /// </summary>
        /// <param name="joinable">the query sentense</param>
        /// <param name="joinType">join type</param>
        /// <param name="field">the lookup field to join</param>
        /// <returns>the query object</returns>
        public static Join Join(this IDirectJoinable joinable, JoinType joinType, LookupQueryField field)
        {
            var sentense = (QuerySentence)joinable;
            return new Join(sentense.Context, joinType, field.FieldName);
        }

        /// <summary>
        /// related join query
        /// </summary>
        /// <param name="joinable">the query sentense</param>
        /// <param name="joinType">join type</param>
        /// <param name="primaryListAlias">the primary list alias</param>
        /// <param name="field">the lookup field to join</param>
        /// <returns></returns>
        public static Join Join(this IRelatedJoinable joinable, JoinType joinType, string primaryListAlias, string field)
        {
            var sentense = (QuerySentence)joinable;
            var primaryJoin = sentense.Context.Joins.FirstOrDefault(x => x.ForeignListAlias == primaryListAlias);
            if (primaryJoin == null)
                throw new Exception("can't find primaryListAlias:" + primaryListAlias);
            return new Join(sentense.Context, joinType, primaryListAlias, field);
        }

        /// <summary>
        /// related join query
        /// </summary>
        /// <param name="joinable">the lookup field to join</param>
        /// <param name="joinType">join type</param>
        /// <param name="primaryListAlias">the primary list alias</param>
        /// <param name="field"></param>
        /// <returns></returns>
        public static Join Join(this IRelatedJoinable joinable, JoinType joinType, string primaryListAlias, LookupQueryField field)
        {
            var sentense = (QuerySentence)joinable;
            var primaryJoin = sentense.Context.Joins.FirstOrDefault(x => x.ForeignListAlias == primaryListAlias);
            if (primaryJoin == null)
                throw new Exception("can't find primaryListAlias:" + primaryListAlias);
            return new Join(sentense.Context, joinType, primaryListAlias, field.FieldName);
        }
        #endregion

    }
}
